/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package systole.processor.filters;

import systole.domain.signals.Segment;



/**
 *
 * @author user
 */
public abstract class Filter implements Cloneable {

    /**
     * The calculated coefficients
     */
    protected double[] coeffs = null;
    /**
     * Sampling period 
     */
    protected double ps;        
    
    /**
     * frequency cut
     */
    protected double cutOffFrequency;


    
    /**
     * @param ps
     */
    public Filter(double ps){
        this.ps = ps;
    }

    //Performs the convolution
    private Segment convol(double[] data, double[] coeffs){

        int dataLen = data.length;
        int operatorLen = coeffs.length;

        double[] freqResponse = new double[dataLen];

        for(int i = 0;i < dataLen-operatorLen;i++){
            freqResponse[i] = 0;

            for(int j = operatorLen-1;j >= 0;j--){
                freqResponse[i] += data[i+j]*coeffs[j];
            }

        }

        return new Segment(freqResponse);
    
    }

    /**
     * Creates the filter coefficients
     * @return coefficients 
     */
    private double[] design(FilterConfiguration fConfig, FilterAlgorithm algorithm){
        if (isCoeffsEmpty()) this.coeffs = algorithm.filter(fConfig);
        return this.coeffs;
    }

    /**
     * @param order
     * @param atten
     * @param ripple
     * @param trband
     * @return filter configuration
     */
    public abstract FilterConfiguration config(int order, double atten, double ripple, double trband);

  

    /**
	 * @return the cutOffFrequency
	 */
	public double getCutOffFrequency() {
		return cutOffFrequency;
	}

	/**
	 * @param cutOffFrequency the cutOffFrequency to set
	 */
	public void setCutOffFrequency(double cutOffFrequency) {
		this.cutOffFrequency = cutOffFrequency;
	}

	/**
     * @param f
     * @return normalize frequency
     */
    protected double normalizeFreq(double f){
        return (f * 0.001); //I want frequencies in KHz
    }

    
    /**
     * calls subclasses design method and calls convolution
     * 
     * @param rawSrc
     * @param fConfig 
     * @param algorithm 
     * @return Segment
     */
    public Segment apply(Segment rawSrc, FilterConfiguration fConfig, FilterAlgorithm algorithm){
        return this.convol(rawSrc.toDoubleArray(),this.design(fConfig, algorithm));
    }

    /**
     * @return Sampling Period
     */
    public double getSamplingPeriod(){return this.ps;}
    /**
     * @return Sampling Frequency
     */
    public double getSamplingFrequency(){ return 1/this.ps;}

    /**
     * @param ps
     */
    public void setSamplingPeriod(double ps){ this.ps = ps;}

    /**
     * 
     */
    public void clearFilterCoeffs(){ this.coeffs = null;}

    /**
     * 
     * @return if is empty
     */
    public boolean isCoeffsEmpty(){ return (this.coeffs == null);}

    @Override
    public Object clone() throws CloneNotSupportedException{
        return super.clone();
    }

}
